package com.sztx.pay.center.common.logback;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;

public class SensitiveConverter extends MessageConverter {
	public static final String MSGNO_NAME = "smsg";
	
	public static final String REGEX_MOBILE = "([^\\d]1\\d{2})\\d{4}(\\d{4}[^\\d])";
	
	public static final String REGEX_ID_CARD = "([^\\d]\\d{6})((19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]))(\\d{4}|\\d{3}X|\\d{3}x)";
	
	public static final String REGEX_BANK_CARD = "([^\\d\\-])(((00[4-6]|018|103|303|356|37[0,4,6,7]|[4,5,6,8,9]\\d{2})\\d{4})(\\d{4,8})(\\d{4}))";
	
	protected Pattern bankPattern = Pattern.compile(REGEX_BANK_CARD); 
	
	@Override
	public String convert(ILoggingEvent event) {		
		String msg = super.convert(event);
	
		String loggerName = event.getLoggerName();		
		if ("jdbc.sqltiming".equals(loggerName)) {
			msg = msg.replaceAll("\\n", " ");
		}
		
		Matcher bankMatcher = bankPattern.matcher(msg);		
		StringBuffer sb = new StringBuffer();
		while (bankMatcher.find() ) {
			String cardNo = bankMatcher.group(2);	
			if (!luhnTest(cardNo)){
				continue;
			}
			
			cardNo = bankMatcher.group(1)+bankMatcher.group(3);
			for (int i = 0; i < bankMatcher.group(5).length(); i++) {
				cardNo += "*";
			}			
			cardNo += bankMatcher.group(6);
			
			bankMatcher.appendReplacement(sb, cardNo);			
		}		
		bankMatcher.appendTail(sb);
		
		msg = sb.toString();
		 
//		return msg;
//		 return msg.replaceAll(REGEX_BANK_CARD, "$1********$4");
//		 return msg.replaceAll(REGEX_ID_CARD, "$1************$7");
//		 return msg.replaceAll(REGEX_MOBILE, "$1****$2");
		 
//		 return msg.replaceAll(REGEX_BANK_CARD, "$1********$3").replaceAll(REGEX_ID_CARD, "$1************$7");
		
		return msg.replaceAll(REGEX_ID_CARD, "$1********$6").replaceAll(REGEX_MOBILE, "$1****$2");
	}
	
	/**
	 * luhn算法
	 * <br>
	 * 参见<link>https://en.wikipedia.org/wiki/Luhn_algorithm#cite_note-0</link>
	 * @param number
	 * @return
	 */
	public static boolean luhnTest(String number){
        int s1 = 0, s2 = 0;
        String reverse = new StringBuffer(number).reverse().toString();
        for(int i = 0 ;i < reverse.length();i++){
            int digit = Character.digit(reverse.charAt(i), 10);
            if(i % 2 == 0){//this is for odd digits, they are 1-indexed in the algorithm
                s1 += digit;
            }else{//add 2 * digit for 0-4, add 2 * digit - 9 for 5-9
                s2 += 2 * digit;
                if(digit >= 5){
                    s2 -= 9;
                }
            }
        }
        return (s1 + s2) % 10 == 0;
    }

}
